<?php
/**
 * [ Random Framework ]
 *
 * @version 2.0.0 (build 20130520)
 *
 * @link http://0x00.sinaapp.com/random.html
 * 
 * @author Coseylee (Coseylee@gmail.com).
 *
 */

final class DB
{
	// 数据库引擎
	static private $driver = null;
	// 表前缀
	static private $prefix = '';
	// 连接池
	static private $link = array();
	// 配置
	static private $config = array();

	/**
	 * 在连接池中增加一个连接
	 * 
	 * @param $name 连接配置名称
	 */
	static function connectAdd($name)
	{
		if ($name == '')
		{
			$name = 'default';
		}

		if (isset($GLOBALS['RANDOM']['db'][$name]) && !empty($GLOBALS['RANDOM']['db'][$name]))
		{
			if (!isset(self::$link[$name]))
			{
				$config = $GLOBALS['RANDOM']['db'][$name];

				// 没有数据库引擎
				if (!isset($config['driver']))
				{
					throw new random_exception('Database Connection Configure Not Set "driver" Item.');
				}
				// 没有数据库名
				if (!isset($config['name']))
				{
					throw new random_exception('Database Connection Configure Not Set "name" Item.');
				}
				// 没有表前缀
				if (!isset($config['prefix']))
				{
					$config['prefix'] = '';
				}

				if (!isset($config['master']))
				{
					throw new random_exception('Database Connection Configure Not Set "master" Item.');
				}
				
				// 主库
				self::$link[$name]['master'] = DB::connectDB($config['driver'], self::getConnectConfig($config['master']) + array('name' => $config['name']));
				unset($driver);

				// 从库
				if (isset($config['slave']) && !empty($config['slave']))
				{
					self::$link[$name]['slave'] = DB::connectDB($config['driver'], self::getConnectConfig($config['slave']) + array('name' => $config['name']));
					unset($driver);
				}
				else
				{
					self::$link[$name]['slave'] = & self::$link[$name]['master'];
				}

				self::$config[ $name ] = $config;
			}
			return $name;
		}
		else
		{
			throw new random_exception('Database Connection Configure ('.$name.') Not Found.');
		}
	}

	/**
	 * 获取连接配置信息
	 * 
	 * @param array $config 配置信息
	 */
	private static function getConnectConfig($config)
	{
		if (array_keys($config) !== range(0, count($config) - 1))
		{
			return $config;
		}
		return $config[ mt_rand(0, count($config) - 1) ];
	}

	/**
	 * 连接数据库
	 * 
	 * @param string $driver 数据库引擎
	 * @param array $config 配置信息
	 */
	private static function connectDB($driver, $config)
	{
		random::import(RANDOM_ROOT.'drivers'.DIR_SEP.$driver.'.driver.php');
		$driver = $driver.'_db';
		if (class_exists($driver))
		{
			return new $driver($config);
		}
		else
		{
			throw new random_exception('Database Driver Class "'.$driver.'" Not Found.');
		}
		return false;
	}

	/**
	 * 获取连接
	 * 
	 * @param $db_config 指定连接池
	 * @param $type 指定主从库
	 */
	static function getConnectDriver($db_config = 'default', $type = 'Master')
	{
		if ($db_config == '' || !isset(self::$link[ $db_config ]))
		{
			$db_config = DB::connectAdd($db_config);
		}

		if ($type === 'Slave')
		{
			self::$driver = self::$link[ $db_config ]['slave'];
		}
		else
		{
			self::$driver = self::$link[ $db_config ]['master'];
		}

		self::$prefix = self::$config[ $db_config ]['prefix'];

		return self::$driver;
	}
	
	/**
	 * Create
	 * 
	 * @param $table 表名
	 * @param $data 数组形式的插入数据
	 * @param $replace 是否替换插入
	 * @param $db_config 指定连接池
	 */
	static function insert($table, $data,  $replace = false, $db_config = '')
	{
		self::getConnectDriver($db_config, 'Master');
		$sql = self::$driver -> insert($table, $data, $replace);
		if ($sql != '' && DB::query($sql, false))
		{
			return DB::insert_id();
		}
		return false;
	}
	
	/**
	 * Read
	 * 
	 * @param $table 表名
	 * @param $where 查询条件（数组或字符串）
	 * @param $order 排序条件（字符串）
	 * @param $limit 限制（字符串）
	 * @param $data 查询字段（字符串）
	 * @param $db_config 指定连接池
	 */
	static function select($table, $where = '', $order = '', $limit = '', $data = '*', $db_config = '')
	{
		self::getConnectDriver($db_config, 'Slave');
		$sql = self::$driver -> select($table, $where, $order, $limit, $data);
		if ($sql != '')
		{
			return DB::query($sql, true);
		}
		return false;
	}
	
	/**
	 * Read One
	 * 
	 * @param $table 表名
	 * @param $where 查询条件（数组或字符串）
	 * @param $order 排序条件（字符串）
	 * @param $data 查询字段（字符串）
	 * @param $db_config 指定连接池
	 */
	static function select_one($table, $where = '', $order = '', $data = '*', $db_config = '')
	{
		self::getConnectDriver($db_config, 'Slave');
		$sql = self::$driver -> select_one($table, $where, $order, $data);
		if ($sql != '')
		{
			$results = DB::query($sql, true);
			if ($results === false) return false;
			return $results[0];
		}
		return false;
	}
	
	/**
	 * Update
	 * 
	 * @param $table 表名
	 * @param $data 数组形式的数据
	 * @param $where 条件（数组或字符串）
	 * @param $db_config 指定连接池
	 * @return $affected_rows 返回影响行数
	 */
	static function update($table, $data, $where, $db_config = '')
	{
		self::getConnectDriver($db_config, 'Master');
		$sql = self::$driver -> update($table, $data, $where);
		if ($sql != '' && DB::query($sql, false))
		{
			return DB::affected_rows();
		}
		return false;
	}
	
	/**
	 * Delete
	 * 
	 * @param $table 表名
	 * @param $where 条件（数组或字符串）
	 * @param $db_config 指定连接池
	 * @return $affected_rows 返回影响行数
	 */
	static function delete($table, $where, $db_config = '')
	{
		self::getConnectDriver($db_config, 'Master');
		$sql = self::$driver -> delete($table, $where);
		if ($sql != '' && DB::query($sql, false))
		{
			return DB::affected_rows();
		}
		return false;
	}
	
	/**
	 * 执行查询语句
	 * 
	 * @param $sql 执行语句
	 * @param $format 是否格式化数据
	 * @param $db_config 指定连接池
	 * @param $type 指定主从库
	 */
	static function query($sql, $format = true, $db_config = '', $type = 'Master')
	{
		if ($db_config !== '')
		{
			self::getConnectDriver($db_config, $type);
		}

		// 表前缀处理
		$sql = str_replace('random_', self::$prefix, $sql);
		
		if (($results = self::$driver -> query($sql)) === false) return false;
		
		if ($format == true)
		{
			return DB::format_result($results);
		}

		return $results;
	}
	
	/**
	 * 返回关联数组
	 * 
	 * @param $results
	 */
	static function fetch_array($results)
	{
		return self::$driver -> fetch_array($results);
	}
	
	/**
	 * 返回索引数组
	 * 
	 * @param $results
	 */
	static function fetch_row($results)
	{
		return self::$driver -> fetch_row($results);
	}
	
	/**
	 * 快速返回下一行结果集（嵌套查询慎用）
	 * 
	 */
	static function fetch_next()
	{
		return self::$driver -> fetch_next();
	}
	
	/**
	 * 格式化结果集为数组
	 * 
	 * @param $results 结果集
	 */
	static function format_result($results)
	{
		$return = array();
		while ($row = self::fetch_array($results))
		{
			$return[] = $row;
		}
		unset($row);
		self::free_result();
		if (empty($return)) return false;
		return $return;
	}
	
	/**
	 * 开始事务
	 * 
	 * @param $db_config 指定连接池
	 */
	static function start($db_config = '')
	{
		return self::getConnectDriver($db_config, 'Master') -> start();
	}
	
	/**
	 * 事务提交
	 * 
	 * @param $db_config 指定连接池
	 */
	static function commit($db_config = '')
	{
		return self::getConnectDriver($db_config, 'Master') -> commit();
	}
	
	/**
	 * 事务回滚
	 * 
	 * @param $db_config 指定连接池
	 */
	static function rollback($db_config = '')
	{
		return self::getConnectDriver($db_config, 'Master') -> rollback();
	}
	
	/**
	 * 分页查询
	 * 
	 * @param $curpage 当前页
	 * @param $perpage 每页条数
	 * @param $table 操作的表名
	 * @param $db_config 需要使用的连接
	 */
	static function pager($curpage = 1, $perpage = 10, $table = '', $db_config = '')
	{
		static $pager = null;
		if ($pager == null)
		{
			$pager = new pager();
		}
		$pager -> setOption($curpage, $perpage, $table, $db_config);
		return $pager;
	}
	
	/**
	 * 释放结果集
	 * 
	 */
	static function free_result()
	{
		return self::$driver -> free_result();
	}
	
	/**
	 * 结果集行数 （一般情况下返回的结果集均为数组形式，所以请使用count()函数计算）
	 * 
	 * @param $results
	 */
	static function num_rows($results = null)
	{
		return self::$driver -> num_rows($results);
	}
	
	/**
	 * 操作受影响的行数
	 * 
	 */
	static function affected_rows()
	{
		return self::$driver -> affected_rows();
	}
	
	/**
	 * 最后插入的自增ID
	 * 
	 */
	static function insert_id()
	{
		return self::$driver -> insert_id();
	}
	
	/**
	 * 查询次数
	 * 
	 */
	static function query_count()
	{
		return self::$driver -> query_count();
	}
	
	/**
	 * 返回所有已执行的语句
	 * 
	 */
	static function sqls()
	{
		return self::$driver -> sqls();
	}
	
	/**
	 * 关闭数据库连接
	 * 
	 * @param $db_config 数据库连接池名称
	 */
	static function close($db_config)
	{
		if ($db_config != '')
		{
			self::getConnectDriver($db_config, 'Master') -> close();
			self::getConnectDriver($db_config, 'Slave') -> close();
		}
		return true;
	}
}


/**
 * DB 内置分页类 (MySQL)
 * 
 * 目前仅支持 DB::pager() -> select 和 DB::pager() -> query()
 * 
 */
class pager
{
	private $db_config = '';
	private $table = '';
	private $curpage = 0;
	private $perpage = 0;
	private $_curpage = 0;
	private $_perpage = 0;
	private $_total = 0;
	private $_pagesize = 0;
		
	function setOption($curpage, $perpage, $table, $db_config)
	{
		$this -> curpage = $curpage ? $curpage : 1;
		$this -> perpage = $perpage ? $perpage : 10;
		$this -> table = $table;
		$this -> db_config = $db_config;
	}
	
	function __call($func, $args)
	{
		if ($func == 'select')
		{
			// 分离参数
			
			if (isset($this -> table) && $this -> table != '')
			{
				$table = $this -> table;
				$offset = -1;
			}
			else
			{
				$table = $args[0];
				$offset = 0;
			}
			
			$where = isset($args[$offset+1]) ? $args[$offset+1] : '';
			$order = isset($args[$offset+2]) ? $args[$offset+2] : '';
			$limit = isset($args[$offset+3]) ? $args[$offset+3] : '';
			$data = isset($args[$offset+4]) ? $args[$offset+4] : '*';
			//list($table, $where, $order, $limit, $data) = $args;
			
			$this -> _curpage = $this -> curpage;
			$this -> _perpage = $this -> perpage;
			// 取得数据总数
			$results = DB::select_one($table, $where, '', 'count(*) as total', $this -> db_config);
			$this -> _total = $results['total'];
			// 计算总页数
			$this -> _pagesize = ceil($this -> _total / $this -> perpage);
			$limit = (($this -> curpage - 1)*$this -> perpage).', '.$this -> perpage;
			// 查询数据
			return DB::select($table, $where, $order, $limit, $data, $this -> db_config);
			//dump(call_user_func_array(array($this -> driver, $func), $args));
		}
		else if ($func == 'query')
		{
			$sql = preg_replace('/(LIMIT\s+\d+(,\d+)?)$/iU', '', $args[0]);
			$count_sql = preg_replace('/^(SELECT)\s+(.*)\s+(FROM)/iU', '$1 count(*) as total $3', $sql);
			$results = DB::query($count_sql, true, $this -> db_config, 'Slave');
			$this -> _curpage = $this -> curpage;
			$this -> _perpage = $this -> perpage;
			// 取得数据总数
			$this -> _total = $results[0]['total'];
			// 计算总页数
			$this -> _pagesize = ceil($this -> _total / $this -> perpage);
			$limit = ' LIMIT '.(($this -> curpage - 1)*$this -> perpage).', '.$this -> perpage;
			// 查询数据
			return DB::query($sql.$limit, true, $this -> db_config, 'Slave');
		}
		else
		{
			throw new random_exception('Pager Method "'.$func.'" Undefined.');
		}
	}
	
	function getPage()
	{
		$return = array(
			'cur_page' => $this -> _curpage,
			'per_page' => $this -> _perpage,
			'total_size' => $this -> _total,
			'page_size' => $this -> _pagesize,
		);
		return $return;
	}
}